第十二章 动态内存
程序运行时的内存划分
- 静态内存:用于存放static数据,包括局部static变量,类static成员,定义在任何函数之外的变量(全局变量)
- 栈内存:存放函数内非static的对象
- 堆(or 自由空间):存放动态分配的对象。使用动态内存的原因有三
程序不知道自己需要多少对象
程序不知道所需对象的具体类型
程序需要在多个对象间共享数据
智能指针
- 新标准:新增了智能指针,使用与常规指针无异,但是它负责自动释放所指向的对象
- 智能指针也是模板
- 没有初始化的智能指针默认值初始化为0值(空)
- 使用get方法获得的内置指针,不能被delete此指针
- 智能指针还能够重写删除器, 在指针所指对象将要被销毁时调用, 用于取代对象的析构函数
shared_ptr
允许指向多个指针指向同一个对象
最安全的分配和使用动态内存的方法就是使用make_shared方法
可以使用auto来简化声明
使用时注意要声明指针类型, 括号中的内容应该对应目标类型的构造函数,类似emplace函数
- 可以认为每个shared_ptr都有一个关联的计数器, 称为引用计数, 一旦技术变为0, 它就会自动释放所管理的对象.(调用目标对象的析构函数)
- reset方法将重置当前指针的值为空或传入的内置指针.
unique_ptr
unique_ptr独占所指的对象, 或称一个unique_ptr拥有它所指向的对象.
unique_ptr的初始化方式和shared_ptr类似, 但是unique_ptr不支持拷贝
- 有一个例外, 即通过函数返回值的形式, 拷贝或赋值一个即将被销毁的unique_ptr
weak_ptr
- weak_ptr是一种不控制目标对象生存期的智能指针, 即指向shared_ptr时, 不会改变它的引用计数
- 创建时需要使用shared_ptr
- 由于weak_ptr所指的对象可能已经被销毁, 因此不能直接访问对象, 而需要用lock(或expired)方法验证
直接管理内存
使用new和delete运算符直接管理动态内存
new
使用new分配的对象是无名的, 需要使用指针记录返回的地址
可以使用默认初始化, 也可以使用构造函数来构建对象, 甚至可以传入对象(进行拷贝初始化)
当内存耗尽时,new会报一个bad_alloc的异常
- 可以向new传入一个参数(nothrow), 来让异常发生时返回空指针
- 可以用shared_ptr显式地接受new分配的内存, 但是不要把智能指针和内置指针混合使用!
delete
内置指针管理的动态内存在被显式释放之前会一直存放(因此很容易出错)
忘记释放
使用已经销毁了的对象
释放两次
传递给delete的指针必须是指向动态分配的内存, 或者空指针
- 一个动态分配的const对象, 虽然不能修改, 但是可以被销毁
动态数组
new type[num]
使用Type* p=new Type[num]; 的方式声明的动态数组,并不是一个数组类型(无法使用begin, end以及范围for)
但是依旧可以用括号或花括号进行数组的初始化
可以创建空数组, 即num=0, 但是无法解引用(类似尾后指针)
销毁动态数组时, 格式为 delete [] p; 空方括号是必须的, 否则其行为是未定义的.
可以用unique_ptr指向一个动态数组
- 无法对这个unique_ptr使用点运算或箭头成员运算符, 但是可以用下标运算符来访问数组中的元素.
allocator
- 位于memory头文件, 能够把内存分配和对象构造分开来, 步骤分别为:
allocate, 分配内存
construct, 构建对象
destroy, 销毁对象
deallocate, 释放内存
- allocator同样是泛型, 需要指明类型.
- Title: 第十二章 动态内存
- Author: Huan Lee
- Created at : 2023-08-20 14:12:10
- Updated at : 2024-02-26 04:53:15
- Link: https://www.mirthfullee.com/2023/08/20/notion-第十二章 动态内存-f6911c2c/
- License: This work is licensed under CC BY-NC-SA 4.0.